using System;
using System.IO;
using Microsoft.VisualBasic;
using System.Windows.Forms;

namespace SoftwareLocker
{
    // Activate Property
    public class TrialMaker
    {
        #region -> Private Variables 

        private string _baseString;
        private string _password;
        private readonly string _softName;
        private string _regFilePath;
        private string _hideFilePath;
        private int _defDays;
        private int _runed;
        private readonly string _text;
        private readonly string _identifier;

        #endregion

        #region -> Constructor 

        /// <summary>
        /// Make new TrialMaker class to make software trial
        /// </summary>
        /// <param name="softwareName">Name of software to make trial</param>
        /// <param name="regFilePath">File path to save password(enrypted)</param>
        /// <param name="hideFilePath">file path for saving hidden information</param>
        /// <param name="text">A text for contacting to you</param>
        /// <param name="trialDays">Default period days</param>
        /// <param name="trialRunTimes">How many times user can run as trial</param>
        /// <param name="identifier">3 Digit string as your identifier to make password</param>
        public TrialMaker(string softwareName,
            string regFilePath, string hideFilePath,
            string text, int trialDays, int trialRunTimes,
            string identifier)
        {
            _softName = softwareName;
            _identifier = identifier;

            SetDefaults();

            _defDays = trialDays;
            _runed = trialRunTimes;

            _regFilePath = regFilePath;
            _hideFilePath = hideFilePath;
            _text = text;
        }

        private void SetDefaults()
        {
            SystemInfo.UseBaseBoardManufacturer = false;
            SystemInfo.UseBaseBoardProduct = false;
            SystemInfo.UseBiosManufacturer = false;
            SystemInfo.UseBiosVersion = false;
            SystemInfo.UseDiskDriveSignature = false;
            SystemInfo.UsePhysicalMediaSerialNumber = true;
            SystemInfo.UseProcessorId = true;
            SystemInfo.UseVideoControllerCaption = false;
            SystemInfo.UseWindowsSerialNumber = false;

            MakeBaseString();
            MakePassword();
        }

        #endregion

        // Make base string (Computer ID)
        private void MakeBaseString()
        {
            _baseString = Encryption.Boring(Encryption.InverseByBase(SystemInfo.GetSystemInfo(_softName), 10));
        }

        private void MakePassword()
        {
            _password = Encryption.MakePassword(_baseString, _identifier);
        }

        /// <summary>
        /// Show registering dialog to user
        /// </summary>
        /// <returns>Type of running</returns>
        public RunTypes ShowDialog()
        {
            // check if registered before
            if (CheckRegister())
                return RunTypes.Full;

            var passDialog = new FrmDialog(_baseString, _password, DaysToEnd(), _runed, _text);
            
            MakeHideFile();

            DialogResult dr = passDialog.ShowDialog();

            if (dr == DialogResult.OK)
            {
                MakeRegFile();
                return RunTypes.Full;
            }
            if (dr == DialogResult.Retry)
                return RunTypes.Trial;
            return RunTypes.Expired;
        }

        // save password to Registration file for next time usage
        private void MakeRegFile()
        {
            FileReadWrite.WriteFile(_regFilePath, _password);
        }

        // Control Registeration file for password
        // if password saved correctly return true else false
        private bool CheckRegister()
        { 
            string password = FileReadWrite.ReadFile(_regFilePath);

            if (_password == password)
                return true;
            return false;
        }

        // from hidden file
        // indicate how many days can user use program
        // if the file does not exists, make it
        private int DaysToEnd()
        {
            var hf = new FileInfo(_hideFilePath);
            if (hf.Exists == false)
            {
                MakeHideFile();
                return _defDays;
            }
            return CheckHideFile();
        }

        // store hidden information to hidden file
        // Date,DaysToEnd,HowManyTimesRuned,BaseString(ComputerID)
        private void MakeHideFile()
        {
            string hideInfo = DateTime.Now.Ticks + ";";
            hideInfo += _defDays + ";" + _runed + ";" + _baseString;
            FileReadWrite.WriteFile(_hideFilePath, hideInfo);
        }

        // Get Data from hidden file if exists
        private int CheckHideFile()
        {
            string[] hideInfo = FileReadWrite.ReadFile(_hideFilePath).Split(';');

            if (_baseString == hideInfo[3])
            {
                int daysToEnd = Convert.ToInt32(hideInfo[1]);
                if (daysToEnd <= 0)
                {
                    _runed = 0;
                    _defDays = 0;
                    return 0;
                }
                var dt = new DateTime(Convert.ToInt64(hideInfo[0]));
                long diffDays = DateAndTime.DateDiff(DateInterval.Day,
                                                     dt.Date, DateTime.Now.Date,
                                                     FirstDayOfWeek.Saturday,
                                                     FirstWeekOfYear.FirstFullWeek);
                
                daysToEnd = Convert.ToInt32(hideInfo[1]);
                _runed = Convert.ToInt32(hideInfo[2]);
                _runed -= 1;

                diffDays = Math.Abs(diffDays);

                _defDays = daysToEnd - Convert.ToInt32(diffDays);
            }
            return _defDays;
        }

        public enum RunTypes
        { 
            Trial = 0,
            Full,
            Expired,
            UnKnown
        }

        #region -> Properties 

        /// <summary>
        /// Indicate File path for storing password
        /// </summary>
        public string RegFilePath
        {
            get
            {
                return _regFilePath;
            }
            set
            {
                _regFilePath = value;
            }
        }

        /// <summary>
        /// Indicate file path for storing hidden information
        /// </summary>
        public string HideFilePath
        {
            get
            {
                return _hideFilePath;
            }
            set
            {
                _hideFilePath = value;
            }
        }

        /// <summary>
        /// Get default number of days for trial period
        /// </summary>
        public int TrialPeriodDays
        {
            get
            {
                return _defDays;
            }
        }

        /// <summary>
        /// Get or Set TripleDES key for encrypting files to save
        /// </summary>
        public byte[] TripleDesKey
        {
            get
            {
                return FileReadWrite.Key;
            }
            set
            {
                FileReadWrite.Key = value;
            }
        }

        #endregion

        #region -> Usage Properties 

        public bool UseProcessorId
        {
            get
            {
                return SystemInfo.UseProcessorId;
            }
            set
            {
                SystemInfo.UseProcessorId = value;
            }
        }

        public bool UseBaseBoardProduct
        {
            get
            {
                return SystemInfo.UseBaseBoardProduct;
            }
            set
            {
                SystemInfo.UseBaseBoardProduct = value;
            }
        }

        public bool UseBaseBoardManufacturer
        {
            get
            {
                return SystemInfo.UseBiosManufacturer;
            }
            set
            {
                SystemInfo.UseBiosManufacturer = value;
            }
        }

        public bool UseDiskDriveSignature
        {
            get
            {
                return SystemInfo.UseDiskDriveSignature;
            }
            set
            {
                SystemInfo.UseDiskDriveSignature = value;
            }
        }

        public bool UseVideoControllerCaption
        {
            get
            {
                return SystemInfo.UseVideoControllerCaption;
            }
            set
            {
                SystemInfo.UseVideoControllerCaption = value;
            }
        }

        public bool UsePhysicalMediaSerialNumber
        {
            get
            {
                return SystemInfo.UsePhysicalMediaSerialNumber;
            }
            set
            {
                SystemInfo.UsePhysicalMediaSerialNumber = value;
            }
        }

        public bool UseBiosVersion
        {
            get
            {
                return SystemInfo.UseBiosVersion;
            }
            set
            {
                SystemInfo.UseBiosVersion = value;
            }
        }

        public bool UseBiosManufacturer
        {
            get
            {
                return SystemInfo.UseBiosManufacturer;
            }
            set
            {
                SystemInfo.UseBiosManufacturer = value;
            }
        }

        public bool UseWindowsSerialNumber
        {
            get
            {
                return SystemInfo.UseWindowsSerialNumber;
            }
            set
            {
                SystemInfo.UseWindowsSerialNumber = value;
            }
        }

        #endregion
    }
}